<?php
declare(strict_types=1);

namespace WebApp\lib\db\postgres;

use Swoole\Coroutine\PostgreSQL;
use WebApp\lib\db\mysql\MysqlTable;

/**
 * Class CoTable
 * @package WebApp\lib\db
 */
class CoTable extends MysqlTable
{
//    /**
//     * @param $arr
//     * @return callable
//     */
//    public function transaction($arr)
//    {
//        return function (PostgresSql $client) use (&$arr) {
//            $client->query('begin transition');
//            try {
//                foreach ($arr as $res) {
//                    if (gettype($res) !== 'object') {
//                        throw new ErrorException();
//                    }
//                    $res = (bool)$res();
//                    if (!$res) {
//                        throw new ErrorException();
//                    }
//                }
//                $client->query('commit transition');
//                return true;
//            } catch (PDOException $e) {
//                $client->query('rollback transition');
//                throw $e;
//            } catch (ErrorException $e) {
//                $client->query('rollback transition');
//                throw $e;
//            }
//        };
//    }
//
//    /**
//     * @param string $sql
//     * @return mixed
//     */
//    public function getObjArrBySql(string $sql)
//    {
//
//        $this->setLastSql($sql);
//        return function (PostgreSQL $client) {
//            return $client->query($this->getLastSql());
//        };
//    }
//
    /**
     * @param string $sql
     * @return mixed
     */
    public function getObjBySql(string $sql)
    {
        $this->setLastSql($sql);
        return function (PostgreSQL $client) use($sql) {
            $result = $client -> query($sql);
            $arr = $client -> fetchAll($result);
            if ($arr) {
                return $arr[0];
            } else {
                return [];
            }
        };
    }
//
//    /**
//     * @param $db_name
//     * @param array $data
//     * @param array $where
//     * @return mixed
//     */
//    public function updateObj($db_name, $data = [], $where = [])
//    {
//        return function (PostgreSQL $client) use (&$db_name, &$data, &$where) {
//            $str = $this->makeWhere($where);
//            $set = $this->makeSetData($data);
//            $this->setLastSql("UPDATE $db_name $set $str");
//            return $client->query($this->getLastSql());
//        };
//    }
//
//    /**
//     * @param $db_name
//     * @param array $where
//     * @return mixed
//     */
//    public function removeObj($db_name, $where = [])
//    {
//        return function (PostgreSQL $client) use (&$db_name, &$where) {
//            $str = $this->makeWhere($where);
//            $this->setLastSql("DELETE FROM $db_name $str");
//            return $client->query($this->getLastSql());
//        };
//    }
//
//    /**
//     * @param $db_name
//     * @param array $data
//     * @return mixed
//     */
//    public function replaceObj($db_name, $data = [])
//    {
//        return function (PostgreSQL $client) use (&$db_name, &$data) {
//            $set = $this->makeSetData($data);
//            $this->setLastSql("REPLACE INTO $db_name $set");
//            return $client->query($this->getLastSql());
//        };
//    }
//
//    /**
//     * @param $db_name
//     * @param array $data
//     * @return mixed
//     */
//    public function addObj($db_name, $data = [])
//    {
//        return function (PostgreSQL $client) use (&$db_name, &$data) {
//            $str = $this->makeSetData($data);
//            $this->setLastSql("INSERT INTO $db_name $str");
//            $res = $client->query($this->getLastSql());
//            if (!$res) {
//                return -1;
//            } else {
//                return $client->insert_id;
//            }
//        };
//    }
//
//    /**
//     * @param $db_name
//     * @param array $where
//     * @return mixed
//     */
//    public function getObjCount($db_name, $where = [])
//    {
//        return  function (PostgreSQL $client) use (&$db_name, &$where) {
//            $str = $this->makeWhere($where);
//            $this->setLastSql("SELECT count(*) as c FROM $db_name $str");
//            $res = $client->query($this->getLastSql());
//            if ($res) {
//                return $res[0]['c'];
//            } else {
//                return false;
//            }
//        };
//    }
//
//    /**
//     * @param $db_name
//     * @param array $need
//     * @param array $where
//     * @param string $group
//     * @param string $sort
//     * @param string $limit
//     * @return mixed
//     */
//    public function getObjArr($db_name, $need = [], $where = [], $group = '', $sort = '', $limit = '')
//    {
//        return function (PostgreSQL $client) use (&$db_name, &$need, &$where, &$group, &$sort, &$limit) {
//            $str = $this->makeWhere($where);
//            $group = $this->makeGroup($group);
//            $sort = $this->makeOrder($sort);
//            $limit = $this->makeLimit($limit);
//            $need = $this->makeNeed($need);
//            $this->setLastSql("SELECT $need FROM $db_name $str $group $sort $limit");
//
//            return $client->query($this->getLastSql());
//        };
//    }
//
    /**
     * @param $db_name
     * @param array $need
     * @param array $where
     * @param string $group
     * @param string $sort
     * @return mixed
     */
    public function getObj($db_name, $need = [], $where = [], $group = '', $sort = '')
    {
        return function (PostgreSQL $client) use (&$db_name, &$need, &$where, &$group, &$sort) {
            var_dump($client);
            $str = $this->makeWhere($where);
            $group = $this->makeGroup($group);
            $sort = $this->makeOrder($sort);
            $need = $this->makeNeed($need);

            return "SELECT $need FROM $db_name $str $group $sort limit 1";
            $this->setLastSql("SELECT $need FROM $db_name $str $group $sort limit 1");
            var_dump($this->getLastSql());
            $result = $client->query($this->getLastSql());
            var_dump($result);
            if (!$result) {
                return [];
            }
            $row = $client->fetchRow($result);
            if (!$row) {
                return [];
            }
            return $row;
        };
    }

    /**
     * @param $data
     * @return mixed
     */
    public function makeSetData(&$data)
    {
        if ($data && is_array($data)) {
            $str = 'SET ';
            foreach ($data as $k => $v) {
                if (is_string($v)) {
                    $v = "'$v'";
                }
                $str .= "{$k}=$v,";
            }
            $str = substr($str, 0, -1);
            return $str;
        } else {
            return '';
        }
    }

    /**
     * @param $where
     * @return mixed
     */
    public function makeWhere(&$where)
    {
        if (is_array($where) && $where) {
            $str = 'WHERE ';
            foreach ($where as $k => $v) {
                if (is_array($v)) {
                    $symbol = $v[0];
                    $v = $v[1];
                } else {
                    $symbol = '=';
                }
                if (is_string($v)) {
                    $v = "'" . $v . "'";
                }
                $str .= "$k" . $symbol . $v . " AND ";
            }
            $str = substr($str, 0, -5);
            return $str;
        } else {
            return '';
        }
    }

    /**
     * @param string $_sql
     * @return mixed
     */
    public function execute(string $_sql)
    {
        $this->setLastSql($_sql);
        return function (PostgreSQL $client) {
            return $client->query($this->getLastSql());
        };
    }

//    public function setLastSql($val)
//    {
//        $this->last_sql = $val;
//    }
//
//    public function setLastId($val)
//    {
//        $this->last_id = $val;
//    }
//
//    public function setLastErr($val)
//    {
//        $this->last_err = $val;
//    }
//
//    public function getLastSql()
//    {
//        return $this->last_sql;
//    }
//
//    public function getLastId()
//    {
//        return $this->last_id;
//    }
//
//    public function getLastErr()
//    {
//        return $this->last_err;
//    }

    /**
     * @param $arr
     * @return callable
     */
    public function transaction($arr)
    {
        // TODO: Implement transaction() method.
    }

    /**
     * @param string $sql
     * @return mixed
     */
    public function getObjArrBySql(string $sql)
    {
        // TODO: Implement getObjArrBySql() method.
    }

    /**
     * @param $dbName
     * @param array $data
     * @param array $where
     * @return mixed
     */
    public function updateObj($dbName, $data = [], $where = [])
    {
        // TODO: Implement updateObj() method.
    }

    /**
     * @param $dbName
     * @param array $where
     * @return mixed
     */
    public function removeObj($dbName, $where = [])
    {
        // TODO: Implement removeObj() method.
    }

    /**
     * @param $dbName
     * @param array $data
     * @return mixed
     */
    public function replaceObj($dbName, $data = [])
    {
        // TODO: Implement replaceObj() method.
    }

    /**
     * @param $dbName
     * @param array $data
     * @return mixed
     */
    public function addObj($dbName, $data = [])
    {
        // TODO: Implement addObj() method.
    }

    /**
     * @param $dbName
     * @param array $where
     * @return mixed
     */
    public function getObjCount($dbName, $where = [])
    {
        // TODO: Implement getObjCount() method.
    }

    /**
     * @param $dbName
     * @param array $need
     * @param array $where
     * @param string $group
     * @param string $sort
     * @param string $limit
     * @return mixed
     */
    public function getObjArr($dbName, $need = [], $where = [], $group = '', $sort = '', $limit = '')
    {
        // TODO: Implement getObjArr() method.
    }
}
